package com.fate.system.controller;

import cn.dev33.satoken.annotation.SaIgnore;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.fate.framework.exception.KKException;
import com.fate.framework.utils.CommonUtil;
import com.fate.framework.utils.RandomValidateCodeUtil;
import com.fate.framework.utils.SmUtil;
import com.fate.system.dto.login.LoginDTO;
import com.fate.system.dto.login.RegisterDTO;
import com.fate.system.entity.User;
import com.fate.system.service.IUserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.Valid;
import java.util.Objects;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

@Slf4j
@Tag(name = "登录操作 API")
@RestController
@RequestMapping("/api/v1.0/login")
public class LoginController {

  @Resource private IUserService userService;

  @Value("${sa-token.token-name}")
  private String tokenName;

  @SaIgnore
  @Operation(summary = "获取验证码")
  @GetMapping(value = "/getVerify")
  public void getVerify(HttpServletRequest request, HttpServletResponse response) {
    try {
      // 设置相应类型,告诉浏览器输出的内容为图片
      response.setContentType("image/jpeg");
      // 设置响应头信息，告诉浏览器不要缓存此内容
      response.setHeader("Pragma", "No-cache");
      response.setHeader("Cache-Control", "no-cache");
      response.setDateHeader("Expire", 0);
      RandomValidateCodeUtil randomValidateCode = new RandomValidateCodeUtil();
      randomValidateCode.getRandomCode(request, response); // 输出验证码图片方法
    } catch (Exception e) {
      log.error("获取验证码失败>>>>   ", e);
    }
  }

  @SaIgnore
  @Operation(summary = "登录")
  @PostMapping("/login_pc")
  public SaTokenInfo login(@RequestBody @Valid LoginDTO loginDTO, HttpSession session) {
//    checkVerify(loginDTO.getCode(), session);
    User user = userService.lambdaQuery().eq(User::getPhone, loginDTO.getPhone()).one();
    checkUserAndPwd(user, loginDTO.getPassword());
    return userService.login(user);
  }

  @Operation(summary = "登出")
  @GetMapping("/logout")
  public void logout() {
    Object loginId = StpUtil.getLoginId();
    SaRequest request = SaHolder.getRequest();
    String tokenValue = request.getHeader(tokenName);
    StpUtil.logoutByTokenValue(tokenValue);
    StpUtil.logout(loginId);
  }

  @SaIgnore
  @Operation(summary = "注册")
  @PostMapping("/register")
  public void register(@RequestBody @Valid RegisterDTO registerDTO) {
    userService.register(registerDTO.getPhone(), registerDTO.getPassword());
  }

  /**
   * 校验验证码
   *
   * @param code 验证码
   * @param session session
   */
  private void checkVerify(String code, HttpSession session) {
    // 从session中获取随机数
    String random = (String) session.getAttribute(RandomValidateCodeUtil.RANDOM_CODE_KEY);
    if (!(random != null && !random.isEmpty() && random.equalsIgnoreCase(code))) {
      throw new KKException("验证码输入错误");
    }
  }

  /**
   * 校验用户是否存在，密码是否正确
   *
   * @param user 用户信息
   * @param pwd 密码
   */
  private void checkUserAndPwd(User user, String pwd) {
    if (CommonUtil.isNullOrEmpty(user)) {
      throw new KKException("用户不存在");
    }

    // 加密密码校验
    String pwdInDatabase = user.getPassword();
    String pwdSM3 = SmUtil.sm3(pwd);
    if (!Objects.equals(pwdSM3, pwdInDatabase)) {
      throw new KKException("密码错误");
    }
  }
}
